<?php

_include(_OTEKOO_UTIL_."Rest");
 _include(_OTEKOO_UTIL_."DataAdapter");
_include(_OTEKOO_UTIL_."MySQLAdapter");
_include(_OTEKOO_MODEL_."DataMapperAbstract");


class APIBootstrap extends REST
{
	public function __construct(){
			parent::__construct();	// Init parent contructor
	}
	
	public function bootstrap()
	{
		$this->init_datalayer();
		
		$this->get_controller_method($controller, $method);
		$controller_file = _OTEKOO_API_.$controller;
		
		$code = 404; //The requested controller does not exist
		if(_include($controller_file))//include the controller file
		{
			if(class_exists($controller, false))
			{
				$controller_obj = new $controller($this);
				if( (method_exists($controller_obj, $method) === TRUE) && ($code = $this->can_be_invoked($controller, $method)) == 0)
					$controller_obj->$method();
			}
		}
		if($code > 0)
			$this->response($code, '');
	}
	
	private function init_datalayer()
	{
		$ini = _OTEKOO_ROOT_."config/db_config.ini";
		if(file_exists($ini))
		{
			$db_config = parse_ini_file($ini, true);
			$this->_db = DataAdapterLoader::getInstance($db_config[_OTEKOO_ENV_]);
			$this->_scripts = new GenericArray($db_config['scripts']);
		}
	}
	
	private function get_controller_method(&$controller, &$method)
	{
		$parts= explode('/', strtolower($this->_request->query) );
		$parts = array_filter($parts, array($this, 'filter'));
		$size = count($parts);
		$controller = "Default";
		$method = "_default";
		if($size == 1)
		{
			$controller = $parts[0];
		}
		else if($size == 2)
		{
			$controller = ucfirst(strtolower($parts[0]));
			$method = $parts[1];
		}
		$controller = "API".$controller;
	}
	
	//@http_method post get put
	private function can_be_invoked($class_name, $method)
	{
		$http_method = strtoupper($this->get_request_method());
		$rc = new ReflectionMethod($class_name, $method);
		if(!$rc->isPublic())
			return 401;
			
		$comment = $rc->getDocComment();
		
		_include("thirdparty/CommentParser");
		$parser = new CommentParser($comment);
		$parser->parse();
		$http_methods = explode(' ', $parser->getParam('http_method'));
		$match = preg_grep("/".$http_method."/i", $http_methods);
		
		return count($match) > 0 ? 0 : 405; //The requested method cannot be invoked by the current http method
	}
	
	private function filter(&$var)
	{
		$var = trim($var);
		return !empty($var);
	}
		
	public function response($status = 200, $data = null)
	{	
		unset($this->_response->debug_messages);
		$dbg = trim(ob_get_contents());
		if(!empty($dbg) && (_OTEKOO_ENV_ == 'dev'))
		{
			$this->_response->debug_messages = $dbg;
		}
		ob_end_clean();
		
		$this->_response->status = array('code'=>$status, 'message'=>$this->get_status_message($status));
		$format = strtolower($this->_request->format);
		if($format == 'xml')
		{
			$data = $this->xmlResponse($this->_response->getData());
			$this->_content_type = 'application/xml';
		}
		else
		{
			$data = $this->json_indent($this->jsonResponse($this->_response->getData()));
			$this->_content_type = 'text/plain';
		}
		parent::response(200, $data);
	}
	
	
	/**
	 * Indents a flat JSON string to make it more human-readable.
	 *
	 * @param string $json The original JSON string to process.
	 *
	 * @return string Indented version of the original JSON string.
	 */
	function json_indent($json) {

		if(_OTEKOO_ENV_ != 'dev')
			return $json;
			
		$result      = '';
		$pos         = 0;
		$strLen      = strlen($json);
		$indentStr   = '  ';
		$newLine     = "\n";
		$prevChar    = '';
		$outOfQuotes = true;

		for ($i=0; $i<=$strLen; $i++) {

			// Grab the next character in the string.
			$char = substr($json, $i, 1);

			// Are we inside a quoted string?
			if ($char == '"' && $prevChar != '\\') {
				$outOfQuotes = !$outOfQuotes;
			
			// If this character is the end of an element, 
			// output a new line and indent the next line.
			} else if(($char == '}' || $char == ']') && $outOfQuotes) {
				$result .= $newLine;
				$pos --;
				for ($j=0; $j<$pos; $j++) {
					$result .= $indentStr;
				}
			}
			
			// Add the character to the result string.
			$result .= $char;

			// If the last character was the beginning of an element, 
			// output a new line and indent the next line.
			if (($char == ',' || $char == '{' || $char == '[') && $outOfQuotes) {
				$result .= $newLine;
				if ($char == '{' || $char == '[') {
					$pos ++;
				}
				
				for ($j = 0; $j < $pos; $j++) {
					$result .= $indentStr;
				}
			}
			
			$prevChar = $char;
		}

		return $result;
	}
}